/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

#include "CSwitchData.h"
#include "PublicLog.h"
#include "SnmpApi.h"
#include "SnmpClient.h"
#include "SnmpResultApi.h"
#include "PublicSnmpCommon.h"
#include "PublicMySql.h"
#include "Common.h"
#include "snmp_packet.h"
//特殊处理端口表采集
//端口表
static const SnmpOidInfo OID_dot1dTpFdbTable={"dot1dTpFdbTable",{1,3,6,1,2,1,17,4,3,1},10};
static const SnmpOidInfo OID_dot1dTpFdbPort={"dot1dTpFdbPort",{1,3,6,1,2,1,17,4,3,1,2},11,ASN_INTEGER};
static const SnmpOidInfo OID_dot1dTpFdbStatus={"dot1dTpFdbStatus",{1,3,6,1,2,1,17,4,3,1,3},11,ASN_INTEGER};
//BasePort
//1.3.6.1.2.1.17.1.4.1.2
static const SnmpOidInfo OID_dot1dBasePortIfIndex ={"dot1dBasePortIfIndex",{1,3,6,1,2,1,17,1,4,1,2},11,ASN_INTEGER};
//H3C交换机才有
//oid.x.mac
static const SnmpOidInfo OID_dot1qTpFdbTable={"dot1qTpFdbTable",{1,3,6,1,2,1,17,7,1,2,2,1},12};
static const SnmpOidInfo OID_dot1qTpFdbPort={"dot1qTpFdbPort",{1,3,6,1,2,1,17,7,1,2,2,1,2},13,ASN_INTEGER};
static const SnmpOidInfo OID_dot1qTpFdbStatus={"dot1qTpFdbStatus",{1,3,6,1,2,1,17,7,1,2,2,1,3},13,ASN_INTEGER};
//思科交换机
static const SnmpOidInfo OID_vtpVlanIfIndex ={"vtpVlanIfIndex",{1,3,6,1,4,1,9,9,46,1,3,1,1,18},14,ASN_INTEGER};
//废弃不使用
void CSwitchData::UpDateBasePortTable(){
}
void CSwitchData::UpDateFdbTable(){
	if(strcmp(m_sysinfo.Manufacturer,"Cisco")==0){
//要先获取vtpVlanIfIndex		
		SETIDLIST idlist;
		idlist.insert(1);
		do{
			netsnmp_variable_list*result=netsnmp_sess_query_walkall(m_ss,OID_vtpVlanIfIndex);
			if(result!=NULL){
				netsnmp_variable_list*resultsave=result;
				while(result!=NULL){
					uint32_t IfIndex=0;
					ReadCount32FromResult(result,OID_vtpVlanIfIndex,IfIndex);		
					if(IfIndex>0)idlist.insert(IfIndex);
					result=result->next_variable;
				}
				SAFE_FREE_VARBIND(resultsave);
			}
		}while(0);
		char DefaultSpecific[64]={0};
		GetSnmpCommunity(m_ip.c_str(),DefaultSpecific,64);
		SETIDLIST::iterator it=idlist.begin();
		while(it!=idlist.end()){
			char Specific[64]={0};
			sprintf(Specific,"%s@%d",DefaultSpecific,*it);
			ChangeSnmpSpecific(m_ss,Specific);
			//WARN("Cisci Use ID %d",*it);
			UpDateFdbTableNormal();
			UpDateBasePortTableNormal();
			it++;
		}
		ChangeSnmpSpecific(m_ss,DefaultSpecific);
	}else{
		UpDateFdbTableNormal();
		UpDateBasePortTableNormal();
	}
}
//思科方法特殊
void CSwitchData::UpDateFdbTableNormal(){
	netsnmp_variable_list*result=netsnmp_sess_query_walkallex(m_ss,OID_dot1dTpFdbPort,OID_dot1dTpFdbStatus);
	if(result!=NULL){
		netsnmp_variable_list*resultsave=result;
		while(result!=NULL){
			MAPFDBTABLE::iterator it=m_FdbTable.end();
			do{
				int rootlen=OID_dot1dTpFdbTable.oidLen;
				FdbTable info;
				memset(&info,0,sizeof(FdbTable));
				OidReadMac(result->name,rootlen+1,info.FdbAddress);		
				it=m_FdbTable.find(info.FdbAddress);
				if(it==m_FdbTable.end()){
					m_FdbTable.insert(std::pair<std::string,FdbTable>(info.FdbAddress,info));
					it=m_FdbTable.find(info.FdbAddress);
				}	
			}while(0);
			if(it!=m_FdbTable.end()){
				if(OID_COMPARE(OID_dot1dTpFdbPort,result)==0){
					ReadCount32FromResult(result,OID_dot1dTpFdbPort,it->second.FdbPort);
				}else
				if(OID_COMPARE(OID_dot1dTpFdbStatus,result)==0){	
					ReadCount32FromResult(result,OID_dot1dTpFdbStatus,it->second.FdbStatus);
				}
			}
			result=result->next_variable;
		}
		SAFE_FREE_VARBIND(resultsave);
	}
}
void CSwitchData::UpDateBasePortTableNormal(){
	netsnmp_variable_list*result=netsnmp_sess_query_walkall(m_ss,OID_dot1dBasePortIfIndex);
	if(result!=NULL){
		netsnmp_variable_list*resultsave=result;
		while(result!=NULL){
			int rootlen=OID_dot1dBasePortIfIndex.oidLen;
			uint32_t BasePort=result->name[rootlen];
			uint32_t BasePortIfIndex=0;
			ReadCount32FromResult(result,OID_dot1dBasePortIfIndex,BasePortIfIndex);		
			MAPUINTLIST::iterator it=m_BasePortTable.find(BasePort);
			if(it==m_BasePortTable.end()){
				m_BasePortTable.insert(std::pair<int,int>(BasePort,BasePortIfIndex));
			}else{
				it->second=BasePortIfIndex;
			}
			result=result->next_variable;
		}
		SAFE_FREE_VARBIND(resultsave);
	}
}